home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / mail.c < prev    next >
C/C++ Source or Header  |  1993-03-19  |  17KB  |  752 lines

  1. /* mail.c -- linked list version by Amberyl */
  2.  
  3. #include <sys/time.h> 
  4. #include <string.h>
  5. #include "config.h"
  6. #include "db.h"
  7. #include "interface.h"
  8.  
  9. #ifdef USE_MAILER
  10.  
  11. #define notify(p,m)           notify_check(p,m,0)
  12.  
  13. extern char *tprintf();
  14.  
  15. extern char *strdup();
  16.  
  17. extern void do_log();
  18.  
  19. struct mail *maildb;
  20. struct mail *tail_ptr;
  21.  
  22. #define HEAD  maildb
  23. #define TAIL  tail_ptr
  24.  
  25. #define DASH_LINE  \
  26.   "--------------------------------------------------------------------------"
  27.  
  28. int mdb_top = 0;        /* total number of messages */
  29.   
  30. /*-------------------------------------------------------------------------*
  31.  *   Basic mail functions
  32.  *-------------------------------------------------------------------------*/
  33.  
  34. struct mail *mail_fetch(player, num)
  35.      dbref player;
  36.      int num;
  37. {
  38.   /* get an arbitrary mail message */
  39.  
  40.   struct mail *mp;
  41.   int i = 0;
  42.  
  43.   for (mp = HEAD; mp != NULL; mp = mp->next) {
  44.     if (mp->to == player)
  45.       i++;
  46.     if (i == num)
  47.       return mp;
  48.   }
  49.  
  50.   return NULL;
  51. }
  52.  
  53. static void count_mail(player, rcount, ucount)
  54.      dbref player;
  55.      int *rcount;
  56.      int *ucount;
  57. {
  58.     /* returns count of read and unread messages as rcount and ucount */
  59.  
  60.     struct mail *mp;
  61.     int rc, uc;
  62.  
  63.     rc = uc = 0;
  64.     for (mp = HEAD; mp != NULL; mp = mp->next) {
  65.     if (mp->to == player) {
  66.         if (mp->read)
  67.         rc++;
  68.         else 
  69.         uc++;
  70.     }
  71.     }
  72.     *rcount = rc;
  73.     *ucount = uc;
  74. }
  75.  
  76. void check_mail(player, show)
  77.      dbref player;
  78.      int show;
  79. {
  80.  
  81.   /* list all mail messages.
  82.    * if !show, then just count the number of messages
  83.    */
  84.  
  85.     struct mail *mp;
  86.     int i = 0;
  87.     int rc;            /* read messages */
  88.     int uc;            /* unread messages */
  89.  
  90.     if (show) {
  91.     /* show all messages */
  92.     notify(player,
  93.  "--------------------------------   MAIL   --------------------------------");
  94.  
  95.     for (mp = HEAD; mp != NULL; mp = mp->next) {
  96.         if (mp->to == player) {
  97.         i++;
  98.         notify(player, tprintf("[%c] %-3d From: %-*s Time: %s",
  99.                        (mp->read) ? ' ' : '*',
  100.                        i,
  101.                        PLAYER_NAME_LIMIT + 1, Name(mp->from),
  102.                        uncompress(mp->time)));
  103.         }
  104.     }
  105.     notify(player, DASH_LINE);
  106.     } else {
  107.     /* just count messages */
  108.     count_mail(player, &rc, &uc);
  109.     if (rc + uc > 0)
  110.         notify(player,
  111.            tprintf("\nMAIL: You have %d messages (%d unread).\n",
  112.                rc + uc, uc));
  113.     else
  114.         notify(player, tprintf("\nMAIL: You have no mail.\n"));
  115.     return;
  116.     }
  117. }
  118.  
  119. void read_mail(player, num)
  120.      dbref player;
  121.      int num;
  122. {
  123.   /* print a mail message */
  124.  
  125.   struct mail *mp;
  126.  
  127.   mp = mail_fetch(player, num);
  128.  
  129.   if (mp != NULL) {
  130.     notify(player, DASH_LINE);
  131.     notify(player, tprintf("From: %-*s Time: %-25s  Status: %s",
  132.                PLAYER_NAME_LIMIT + 1, Name(mp->from),
  133.                uncompress(mp->time),
  134.                (mp->read) ? "Read" : "Unread"));
  135.     notify(player, DASH_LINE);
  136.     notify(player, uncompress(mp->message));
  137.     notify(player, DASH_LINE);
  138.     mp->read = 1;        /* mark message as read */
  139.     return;
  140.   }
  141.  
  142.   /* ran off the end of the list without finding anything */
  143.   notify(player, "You don't have that many messages!");
  144.   return;
  145. }
  146.  
  147. void send_mail(player, target, message)
  148.      dbref player;
  149.      dbref target;
  150.      const char *message;
  151. {
  152.   /* send a mail message */
  153.  
  154.   struct mail *newp;
  155.   time_t tt;
  156.   char tbuf1[30];
  157.  
  158.   if (Typeof(target) != TYPE_PLAYER) {
  159.     notify(player, "You cannot send mail to non-existent people.");
  160.     return;
  161.   }
  162.  
  163.   tt = time(NULL);
  164.   strcpy(tbuf1, ctime(&tt));
  165.   tbuf1[strlen(tbuf1) - 1] = '\0';       /* whack the newline */
  166.  
  167.   /* initialize the appropriate fields */
  168.   newp = (struct mail *) malloc(sizeof(struct mail));
  169.   newp->to = target;
  170.   newp->from = player;
  171.   newp->message = (char *) strdup(compress(message));
  172.   newp->time = (char *) strdup(compress(tbuf1));
  173.   newp->read = 0;
  174.   newp->prev = TAIL;
  175.   newp->next = NULL;
  176.  
  177.   /* if this is the first message, it is the head and the tail */
  178.   if (mdb_top == 0) {
  179.     HEAD = newp;
  180.     TAIL = newp;
  181.   } else
  182.     TAIL->next = newp;
  183.  
  184.   /* the new message becomes the tail */
  185.   TAIL = newp;
  186.   mdb_top++;
  187.  
  188.   /* notify people */
  189.   notify(player, tprintf("You sent your message to %s.", Name(target)));
  190.   notify(target, tprintf("MAIL: You have a new message from %s.", 
  191.              Name(player)));
  192.   
  193.   return;
  194. }
  195.  
  196. void clear_mail(player, num)
  197.      dbref player;
  198.      int num;
  199. {
  200.   /* if num is 0, clear all of the player's mail. Otherwise, clear one. */
  201.  
  202.   struct mail *mp, *nextp;
  203.  
  204.   if (!num) {
  205.     /* clear all */
  206.     for (mp = HEAD; mp != NULL; mp = nextp) {
  207.       if (mp->to == player) {
  208.     /* head and tail of the list are special */
  209.     if (mp == HEAD)
  210.       HEAD = mp->next;
  211.     else if (mp == TAIL)
  212.       TAIL = mp->prev;
  213.     /* relink the list */
  214.     if (mp->prev != NULL)
  215.       mp->prev->next = mp->next;
  216.     if (mp->next != NULL)
  217.       mp->next->prev = mp->prev;
  218.     /* save the pointer */
  219.     nextp = mp->next;
  220.     /* then wipe */
  221.     mdb_top--;
  222.     free(mp->message);
  223.     free(mp->time);
  224.     free(mp);
  225.       } else
  226.     nextp = mp->next;
  227.     }
  228.     notify(player, "Mailbox cleared.");
  229.     return;
  230.   } else {
  231.     /* find the message and clear just that one */
  232.     mp = mail_fetch(player, num);
  233.     if (mp != NULL) {
  234.       /* got it. delete. */
  235.       /* head and tail of the list are special */
  236.       if (mp == HEAD)
  237.     HEAD = mp->next;
  238.       else if (mp == TAIL)
  239.     TAIL = mp->prev;
  240.       /* relink the list */
  241.       if (mp->prev != NULL)
  242.     mp->prev->next = mp->next;
  243.       if (mp->next != NULL)
  244.     mp->next->prev = mp->prev;
  245.       /* then wipe */
  246.       mdb_top--;
  247.       free(mp->message);
  248.       free(mp->time);
  249.       free(mp);
  250.       notify(player, tprintf("Message #%d cleared.", num));
  251.       return;
  252.     }
  253.     /* didn't find anything */
  254.     notify(player, "You don't have that many messages!");
  255.     return;
  256.   }
  257. }
  258.  
  259. void purge_mail(player)
  260.      dbref player;
  261. {
  262.   /* wipes the entire maildb */
  263.  
  264.   struct mail *mp, *nextp;
  265.  
  266.   if (!Wizard(player)) {
  267.     notify(player, "The postal service issues a warrant for your arrest.");
  268.     return;
  269.   }
  270.  
  271.   /* walk the list */
  272.   for (mp = HEAD; mp != NULL; mp = nextp) {
  273.     nextp = mp->next;
  274.     free(mp->message);
  275.     free(mp->time);
  276.     free(mp);
  277.   }
  278.  
  279.   HEAD = TAIL = NULL;
  280.   mdb_top = 0;
  281.  
  282.   do_log(LT_ERR, 0, 0, "** MAIL PURGE ** done by %s(#%d).", 
  283.      Name(player), player);
  284.   notify(player, "You annihilate the post office. All messages cleared.");
  285. }
  286.  
  287. void do_mail_debug(player, action, victim)
  288.      dbref player;
  289.      char *action;
  290.      char *victim;
  291. {
  292.   /* how to fix mail with a sledgehammer */
  293.  
  294.   dbref target;
  295.   struct mail *mp;
  296.   int i;
  297.  
  298.   if (!Wizard(player)) {
  299.     notify(player, "Go get some bugspray.");
  300.     return;
  301.   }
  302.  
  303.   if (string_prefix("clear", action)) {
  304.     target = lookup_player(victim);
  305.     if (target == NOTHING) {
  306.       init_match(player, victim, NOTYPE);
  307.       match_absolute();
  308.       target = match_result();
  309.     }
  310.     if (target == NOTHING) {
  311.       notify(player, tprintf("%s: no such player.", victim));
  312.       return;
  313.     }
  314.     clear_mail(target, 0);
  315.     notify(player, tprintf("Mail cleared for %s(#%d).", Name(target), target));
  316.     return;
  317.   } else if (string_prefix("sanity", action)) {
  318.     for (i = 0, mp = HEAD; mp != NULL; i++, mp = mp->next) {
  319.       if (!GoodObject(mp->to))
  320.     notify(player, tprintf("Bad object #%d has mail.", mp->to));
  321.       else if (Typeof(mp->to) != TYPE_PLAYER)
  322.     notify(player, tprintf("%s(#%d) has mail but is not a player.",
  323.                    Name(mp->to), mp->to));
  324.     }
  325.     if (i != mdb_top) {
  326.       notify(player, 
  327.          tprintf(
  328.                "Mail database top is %d, actual message count is %d. Fixing.",
  329.              mdb_top, i));
  330.       mdb_top = i;
  331.     }
  332.     notify(player, "Mail sanity check completed.");
  333.   } else {
  334.     notify(player, "That is not a debugging option.");
  335.     return;
  336.   }
  337. }
  338.   
  339. void do_mail_stats(player, name, full)
  340.      dbref player;
  341.      char *name;
  342.      int full;
  343. {
  344.   /* mail database statistics */
  345.  
  346.   dbref target;
  347.   int fr, fu, tr, tu, fchars, tchars;
  348.   char last[50];
  349.   struct mail *mp;
  350.  
  351.   fr = fu = tr = tu = fchars = tchars = 0;
  352.  
  353.   /* find player */
  354.  
  355.   if (*name == '\0') {
  356.     if Wizard(player)
  357.       target = AMBIGUOUS;
  358.     else
  359.       target = player;
  360.   } else if (*name == NUMBER_TOKEN) {
  361.     target = atoi(&name[1]);
  362.     if (!GoodObject(target) || (Typeof(target) != TYPE_PLAYER))
  363.       target = NOTHING;
  364.   } else if (!strcasecmp(name, "me")) {
  365.     target = player;
  366.   } else {
  367.     target = lookup_player(name);
  368.   }
  369.  
  370.   if (target == NOTHING) {
  371.     init_match(player, name, NOTYPE);
  372.     match_absolute();
  373.     target = match_result();
  374.   }
  375.  
  376.   if (target == NOTHING) {
  377.     notify(player, tprintf("%s: No such player.", name));
  378.     return;
  379.   }
  380.  
  381.   if (!Wizard(player) && (target != player)) {
  382.     notify(player, "The post office protects privacy!");
  383.     return;
  384.   }
  385.  
  386.   /* this comand is computationally expensive */
  387.  
  388.   if (options.daytime) {
  389.     notify(player, "Sorry, that command has been temporarily disabled.");
  390.     return;
  391.   }
  392.  
  393.   if (!payfor(player, FIND_COST)) {
  394.     notify(player, tprintf("Finding mail stats costs %d %s.", FIND_COST,
  395.                (FIND_COST == 1) ? MONEY: MONIES));
  396.     return;
  397.   }
  398.  
  399.   if (target == AMBIGUOUS) {    /* stats for all */
  400.     if (full == 0) {
  401.       notify(player, 
  402.          tprintf("There are %d messages in the mail spool.", mdb_top));
  403.       return;
  404.     } else if (full == 1) {
  405.       for (mp = HEAD; mp != NULL; mp = mp->next) {
  406.     if (mp->read)
  407.       fr++;
  408.     else
  409.       fu++;
  410.       }
  411.       notify(player, 
  412.          tprintf("There are %d messages in the mail spool, %d unread.",
  413.              fr + fu, fu));
  414.       return;
  415.     } else {
  416.       for (mp = HEAD; mp != NULL; mp = mp->next) {
  417.     if (mp->read) {
  418.       fr++;
  419.       fchars += strlen((char *) uncompress(mp->message));
  420.     } else {
  421.       fu++;
  422.       tchars += strlen((char *) uncompress(mp->message));
  423.     }
  424.       }
  425.       notify(player,
  426.          tprintf(
  427.        "There are %d old messages in the mail spool, totalling %d characters.",
  428.              fr, fchars));
  429.       notify(player,
  430.          tprintf(
  431.        "There are %d new messages in the mail spool, totalling %d characters.",
  432.              fu, tchars));
  433.       return;
  434.     }
  435.   }
  436.  
  437.   /* individual stats */
  438.  
  439.   if (full == 0) {
  440.     /* just count number of messages */
  441.     for (mp = HEAD; mp != NULL; mp = mp->next) {
  442.       if (mp->from == target)
  443.     fr++;
  444.       if (mp->to == target)
  445.     tr++;
  446.     }
  447.     notify(player, tprintf("%s sent %d messages.", 
  448.                Name(target), fr));
  449.     notify(player, tprintf("%s has %d messages.", Name(target), tr));
  450.     return;
  451.   }
  452.  
  453.   /* more detailed message count */
  454.   for (mp = HEAD; mp != NULL; mp = mp->next) {
  455.     if (mp->from == target) {
  456.       if (mp->read)
  457.     fr++;
  458.       else
  459.     fu++;
  460.       if (full == 2)
  461.     fchars += strlen((char *) uncompress(mp->message));
  462.     }
  463.     if (mp->to == target) {
  464.       if (!tr && !tu)
  465.     strcpy(last, (char *) uncompress(mp->time));
  466.       if (mp->read)
  467.     tr++;
  468.       else
  469.     tu++;
  470.       if (full == 2)
  471.     tchars += strlen((char *) uncompress(mp->message));
  472.     }
  473.   }
  474.  
  475.   notify(player, tprintf("Mail statistics for %s:", Name(target)));
  476.  
  477.   if (full == 1) {
  478.     notify(player, tprintf("%d messages sent, %d unread.", fr + fu, fu));
  479.     notify(player, tprintf("%d messages received, %d unread.", tr + tu, tu));
  480.   } else {
  481.     notify(player, 
  482.        tprintf("%d messages sent, %d unread, totalling %d characters.",
  483.            fr + fu, fu, fchars));
  484.     notify(player,
  485.        tprintf("%d messages received, %d unread, totalling %d characters.",
  486.            tr + tu, tu, tchars));
  487.   }
  488.   
  489.   if (tr + tu > 0)
  490.     notify(player, tprintf("Last is dated %s", last));
  491.   return;
  492. }
  493.  
  494.  
  495. /*-------------------------------------------------------------------------*
  496.  *   Main mail routine
  497.  *-------------------------------------------------------------------------*/
  498.  
  499. void do_mail(player, arg1, arg2)
  500.      dbref player;
  501.      char *arg1;
  502.      char *arg2;
  503. {
  504.   int num;
  505.   dbref target;
  506.  
  507.   if (Typeof(player) != TYPE_PLAYER) {
  508.     notify(player, "Only players may send and receive mail.");
  509.     return;
  510.   }
  511.   
  512.   if (!arg1 || !*arg1) {
  513.     if (arg2 && *arg2) {
  514.       notify(player, "Invalid mail command.");
  515.       return;
  516.     }
  517.     /* just the "@mail" command */
  518.     check_mail(player, 1);
  519.     return;
  520.   }
  521.  
  522.   /* purge maildb */  
  523.   if (!strcasecmp(arg1, "mdb-purge")) {
  524.     purge_mail(player);
  525.     return;
  526.   }
  527.  
  528.   /* clear message */
  529.   if (!strcasecmp(arg1, "clear")) {
  530.     if (arg2 && *arg2) {
  531.       /* one message */
  532.       num = atoi(arg2);
  533.       if (!num) {
  534.     notify(player, "Invalid message number.");
  535.     return;
  536.       }
  537.       clear_mail(player, num);
  538.       return;
  539.     } else {
  540.       /* all messgaes */
  541.       clear_mail(player, 0);
  542.       return;
  543.     }
  544.   }
  545.  
  546.   if (arg2 && *arg2) {
  547.     num = atoi(arg1);
  548.     if (num) {
  549.       /* reply to a mail message */
  550.       struct mail *temp;
  551.       temp = mail_fetch(player, num);
  552.       if (!temp) {
  553.     notify(player, "You can't reply to nonexistant mail.");
  554.     return;
  555.       }
  556.       send_mail(player, temp->from, arg2);
  557.       return;
  558.     } else {
  559.       /* send a new mail message */
  560.       if (!arg2 || !*arg2) {
  561.     notify(player, "You can't send blank messages.");
  562.     return;
  563.       }
  564.       target = lookup_player(arg1);
  565.       if ((target == NOTHING) || (Typeof(target) != TYPE_PLAYER)) {
  566.     notify(player, "No such player.");
  567.     return;
  568.       }
  569.       send_mail(player, target, arg2);
  570.       return;
  571.     }
  572.   } else {
  573.     /* attempt to read a mail message */
  574.     num = atoi(arg1);
  575.     if (!num) {
  576.       notify(player, "Invalid mail message.");
  577.       return;
  578.     }
  579.     read_mail(player, num);
  580.     return;
  581.   }
  582.  
  583.   /* if we've hit this point, something is wrong */
  584.   do_log(LT_ERR, 0, 0,
  585.     "MAIL COMMAND PROBLEM: player = %d, arg1 = %s, arg2 = %s",
  586.       player, arg1, arg2);
  587.   return;
  588. }
  589.  
  590. /*-------------------------------------------------------------------------*
  591.  *   Auxiliary functions
  592.  *-------------------------------------------------------------------------*/
  593.  
  594. void fun_mail(buff, args, nargs, privs, dumm1)
  595.      char *buff;
  596.      char *args[10];
  597.      int nargs;
  598.      dbref privs;
  599.      dbref dumm1;
  600. {
  601.     /* This function can take one of three formats:
  602.      *    1.  mail(num)  --> returns message <num> for privs.
  603.      *    2.  mail(player)  --> returns number of messages for <player>.
  604.      *    3.  mail(player, num)  --> returns message <num> for <player>.
  605.      */
  606.  
  607.     struct mail *mp;
  608.     dbref player;
  609.     int num, rc, uc;
  610.  
  611.     /* make sure we have the right number of arguments */
  612.     if ((nargs != 1) && (nargs != 2)) {
  613.     strcpy(buff, "#-1 FUNCTION (MAIL) EXPECTS 1 OR 2 ARGUMENTS");
  614.     return;
  615.     }
  616.  
  617.     if (nargs == 1) {
  618.     if (!is_number(args[0])) {
  619.         /* handle the case of wanting to count the number of messages */
  620.         if ((player = lookup_player(args[0])) == NOTHING) {
  621.         strcpy(buff, "#-1 NO SUCH PLAYER");
  622.         return;
  623.         } else if ((privs != player) && !Wizard(privs)) {
  624.         strcpy(buff, "#-1 PERMISSION DENIED");
  625.         return;
  626.         } else {
  627.         count_mail(player, &rc, &uc);
  628.         sprintf(buff, "%d %d", rc, uc);
  629.         return;
  630.         }
  631.     } else {
  632.         player = privs;
  633.         num = atoi(args[0]);
  634.     }
  635.     } else {
  636.     if ((player = lookup_player(args[0])) == NOTHING) {
  637.         strcpy(buff, "#-1 NO SUCH PLAYER");
  638.         return;
  639.     } else if ((privs != player) && !Wizard(privs)) {
  640.         strcpy(buff, "#-1 PERMISSION DENIED");
  641.         return;
  642.     }
  643.     num = atoi(args[1]);
  644.     }
  645.  
  646.     if ((num < 1) || (num > mdb_top) || (Typeof(player) != TYPE_PLAYER)) {
  647.     strcpy(buff, "#-1 NO SUCH MESSAGE");
  648.     return;
  649.     }
  650.  
  651.     mp = mail_fetch(player, num);
  652.     if (mp != NULL) {
  653.     strcpy(buff, (char *) uncompress(mp->message));
  654.     return;
  655.     }
  656.  
  657.     /* ran off the end of the list without finding anything */
  658.     strcpy(buff, "#-1 NO SUCH MESSAGE");
  659. }
  660.  
  661. int dump_mail(fp)
  662.      FILE *fp;
  663. {
  664.   struct mail *mp;
  665.   int count = 0;
  666.  
  667.   fprintf(fp, "%d\n", mdb_top);
  668.  
  669.   for (mp = HEAD; mp != NULL; mp = mp->next) {
  670.     putref(fp, mp->to);
  671.     putref(fp, mp->from);
  672.     putstring(fp, uncompress(mp->time));
  673.     putstring(fp, uncompress(mp->message));
  674.     putref(fp, mp->read);
  675.     count++;
  676.   }
  677.   
  678.   fprintf(fp, "*** END OF DUMP ***\n");
  679.   fflush(fp);
  680.  
  681.   if (count != mdb_top) {
  682.     do_log(LT_ERR, 0, 0, "MAIL: Count of messages is %d, mdb_top is %d.",
  683.        count, mdb_top);
  684. /*    mdb_top = count;    */
  685. /*  Removed since it won't make a difference unless the process isn't forked */
  686.   }
  687.  
  688.   return (count);
  689. }
  690.  
  691. void mail_init()
  692. {
  693.   mdb_top = 0;
  694.   HEAD = NULL;
  695.   TAIL = NULL;
  696. }
  697.  
  698. int load_mail(fp)
  699.      FILE *fp;
  700. {
  701.   char nbuf1[8];
  702.   int mail_top = 0;
  703.   int i = 0;
  704.   struct mail *mp, *prevp;
  705.  
  706.   mail_init();
  707.  
  708.   /* find out how many messages we should be loading */
  709.   fgets(nbuf1, sizeof(nbuf1), fp);
  710.   mail_top = atoi(nbuf1);
  711.  
  712.   /* first one is a special case */
  713.   mp = (struct mail *) malloc(sizeof(struct mail));
  714.   mp->to = getref(fp);
  715.   mp->from = getref(fp);
  716.   mp->time = (char *) strdup(compress(getstring_noalloc(fp)));
  717.   mp->message = (char *) strdup(compress(getstring_noalloc(fp)));
  718.   mp->read = getref(fp);
  719.   mp->next = NULL;
  720.   mp->prev = NULL;
  721.   HEAD = mp;
  722.   prevp = mp;
  723.   i++;
  724.  
  725.   /* now loop through */
  726.   for ( ; i < mail_top; i++) {
  727.     mp = (struct mail *) malloc(sizeof(struct mail));
  728.     mp->to = getref(fp);
  729.     mp->from = getref(fp);
  730.     mp->time = (char *) strdup(compress(getstring_noalloc(fp)));
  731.     mp->message = (char *) strdup(compress(getstring_noalloc(fp)));
  732.     mp->read = getref(fp);
  733.     mp->next = NULL;
  734.     mp->prev = prevp;
  735.     prevp->next = mp;
  736.     prevp = mp;
  737.   }
  738.  
  739.   TAIL = mp;
  740.  
  741.   mdb_top = i;
  742.  
  743.   if (i != mail_top) {
  744.     fprintf(stderr, "MAIL: mail_top is %d, only read in %d messages.\n",
  745.         mail_top, i);
  746.   }
  747.  
  748.   return (mdb_top);
  749. }
  750.  
  751. #endif                /* USE_MAILER */
  752.